//
//  SYBasicAuthentication.m
//  BasicSDKDemo
//
//  Created by huchu on 2018/8/3.
//  Copyright © 2018年 sysjones. All rights reserved.
//

#import "SYBasicAuthentication.h"
#import <UIKit/UIKit.h>
#import "YYKit.h"

/**
 @param s A string
 @param p A string includes "?" and "*"
 @return A boolean
 */
static bool isMatch(const char *s, const char *p) {
    if(s == NULL && p == NULL)   return true;
    int m = (int)strlen(s);
    int n = (int)strlen(p);
    if(m == 0 && n == 0)   return true;
    int si = 0, pi = 0;
    int xidx = -1, mtch = -1;
    while(si < m){
        if(pi < n && (*(p+pi)=='*')){
            xidx = pi++;
            mtch = si;   // si对应xidx的位置
        }else if(pi < n && (*(s+si) == *(p+pi) || *(p+pi) == '?')){
            ++ si;
            ++ pi;
        }else if(xidx > -1){  // 上一个 '*' 的位置
            pi = xidx + 1;
            si = ++ mtch;
        }else{
            return false;
        }
    }
    while(pi < n && (*(p+pi) == '*'))  ++ pi;
    return (pi == n);
}
@implementation SYBasicAuthentication {
    NSMutableArray *bundleIds;
    NSString *initAuthFile;
}
+(void)load {
    //[self test];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(requestAuthorization) name:UIApplicationDidFinishLaunchingNotification object:nil];
    });
}
+(void)requestAuthorization { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    SYBasicAuthentication*auth =[SYBasicAuthentication new];
    [auth readAllBundleId];
    NSString *bundleID =[UIApplication sharedApplication].appBundleID;
    if (![auth matchBundleIDExisted:bundleID]) {
        NSException*exp= [NSException exceptionWithName:@"鉴权" reason:[NSString stringWithFormat:@"鉴权失败: bundleID:%@", [UIApplication sharedApplication].appBundleID] userInfo:nil];
        [exp raise];
    }
});
}
+(void)testString:(NSString*)orginstring{
    NSString*enc = [self EncryptString:orginstring];
    NSLog(@"%@", enc);
    NSString*dec= [self DecryptString:enc];
    NSLog(@"%@", dec);
}
+(NSString*)EncryptString:(NSString*)string{
    NSData*encriptData = [[string dataValue] aes256EncryptWithKey: [@"1234567890-=1234" dataUsingEncoding:NSUTF8StringEncoding] iv:[@"1234567890123456" dataValue]];
    NSString*enscriptString=[encriptData base64EncodedString];
    return enscriptString;
}
+(NSString*)DecryptString:(NSString*)string{
    NSData*encriptData2 = [NSData dataWithBase64EncodedString:string];
    NSData*dedata = [encriptData2 aes256DecryptWithkey:[@"1234567890-=1234" dataUsingEncoding:NSUTF8StringEncoding] iv:[@"1234567890123456" dataValue]];
    NSString*decryptString = [[NSString alloc] initWithData:dedata encoding:NSUTF8StringEncoding];
    return decryptString;
}
+(void)test{
    bool a=   isMatch([@"asdfasdf" cStringUsingEncoding:NSUTF8StringEncoding], [@"com.syasdf.*" cStringUsingEncoding:NSUTF8StringEncoding]);
    a=   isMatch([@"com.syasdf.1231231.123124" cStringUsingEncoding:NSUTF8StringEncoding], [@"com.syasdf.*" cStringUsingEncoding:NSUTF8StringEncoding]);
    a=   isMatch([@"com.syasdf.1231231" cStringUsingEncoding:NSUTF8StringEncoding], [@"com.syasdf.*" cStringUsingEncoding:NSUTF8StringEncoding]);
    [self testString:@"123"];
    [self testString:@"adsfasdfasdf"];
    [self testString:@"zcxvzxcvzxcvzxcvzxvzxcvzxcvzxcvxzvxcvzxcvzxcvzxvzxcv"];
}
-(instancetype)init{
    self=[super init];
    initAuthFile = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"AuthenticationBunldes.plist"];
    return self;
}
-(void)saveToDisk{
}
-(BOOL)matchBundleIDExisted:(NSString*)bundleID {
    __block BOOL match= false;
    [self->bundleIds enumerateObjectsUsingBlock:^(NSString*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSString*dec = [self.class DecryptString:obj];
        if ([dec rangeOfString:@"*"].length||[dec rangeOfString:@"?"].length) {
            match = isMatch([bundleID cStringUsingEncoding:NSUTF8StringEncoding], [dec cStringUsingEncoding:NSUTF8StringEncoding]);
        }else{
            match = [bundleID isEqualToString:dec];
        }
        if (match) {
            *stop=YES;
        }
    }];
    return match;
}
-(BOOL)checkBunleIDExisted:(NSString *)bundleID{
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF == %@", bundleID];
    if ([self->bundleIds filteredArrayUsingPredicate:predicate].count == 0){
        return NO;
    }
    return YES;
}
-(BOOL)addBundleId:(NSString *)bundleID {
    if (!bundleIds){
        bundleIds=@[].mutableCopy;
    }
    NSString* encBundleID=[self.class EncryptString:bundleID];
    if(![self checkBunleIDExisted:encBundleID]){
        [self->bundleIds addObject:encBundleID];
        [self saveToDisk];
        return YES;
    }else{
        return NO;
    }
}
-(void)removeBundleId:(NSString *)bundleID {
    NSString* encBundleID=[self.class EncryptString:bundleID];
    [self->bundleIds removeObject:encBundleID];
}
-(void)addBundleIdFromFile:(NSString *)file {
    NSArray *array =[NSArray arrayWithContentsOfFile:file];
    [self->bundleIds addObjectsFromArray:array];
    [self saveToDisk];
}
-(void)readAllBundleId{
    self->bundleIds= [NSArray arrayWithPlistData:[NSData dataWithContentsOfFile:initAuthFile]].mutableCopy;
}
-(void)exportBundleIdsToDestPath:(NSString *)path{
    [self->bundleIds writeToFile:path atomically:YES];
    NSLog(@"导出成功:%@", path);
}
-(void)exportDecBundleIdsToDestPath:(NSString*)path{
    NSMutableArray*array2=@[].mutableCopy;
    [self->bundleIds enumerateObjectsUsingBlock:^(NSString*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [array2 addObject:[self.class DecryptString:obj]];
    }];
    [array2 writeToFile:path atomically:YES];
    NSLog(@"导出成功:%@", path);
}
-(void)importDecryptionBundleIdsFromPath:(NSString*)path{
    NSArray*array = [NSArray arrayWithContentsOfFile:path];
    NSMutableArray*array2=@[].mutableCopy;
    [array enumerateObjectsUsingBlock:^(NSString*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [array2 addObject:[self.class EncryptString:obj]];
    }];
    self->bundleIds=array2;
}
@end
